﻿using System;
using System.Linq;
using System.Web.Mvc;
using SharpArch.NHibernate.Web.Mvc;
using MvcContrib;
using ToyStore.Domain.Contracts.Tasks;
using ToyStore.Domain.Store;
using ToyStore.Domain.System;
using ToyStore.Infrastructure;
using ToyStore.Tasks;
using ToyStore.Web.Mvc.Authentication;
using ToyStore.Web.Mvc.Common;
using ToyStore.Web.Mvc.Controllers.ViewModels;

namespace ToyStore.Web.Mvc.Controllers
{
    public class CartController : Controller
    {
		private readonly ICartTask _cartTask;
    	private readonly IExRepository<User> _userRepository;
    	private readonly IExRepository<Product> _productRepository;
		private readonly IExRepository<Cart> _cartRepository;

    	/// <summary>
    	/// Konstruktor.
    	/// </summary>
    	/// <param name="cartTask"></param>
    	/// <param name="userRepository"> </param>
    	/// <param name="productRepository"> </param>
    	/// <param name="cartRepository"> </param>
    	public CartController(ICartTask cartTask, IExRepository<User> userRepository, IExRepository<Product> productRepository, IExRepository<Cart> cartRepository)
		{
			_cartTask = cartTask;
			_userRepository = userRepository;
    		_productRepository = productRepository;
    		_cartRepository = cartRepository;
		}

		/// <summary>
		/// Pobranie lub stworzenie koszyka.
		/// </summary>
		/// <returns></returns>
		private Cart GetCart()
		{
			Cart cart = null;
			if (HttpContext.Session[CartTask.CartSessionGuid] == null)
			{
				cart = _cartTask.CreateCart();
				HttpContext.Session[CartTask.CartSessionGuid] = cart;
			}
			else
			{
				Cart cartFromSession = (Cart)HttpContext.Session[CartTask.CartSessionGuid];
				cart = _cartTask.GetCartByGuid(cartFromSession.CartGuid);
			}
			return cart;
		}

    	/// <summary>
		/// Wyswietlenie produktow w koszyku.
		/// </summary>
		/// <returns></returns>
        public ActionResult Index()
    	{
    		Cart cart = null;
			if (HttpContext.Session[CartTask.CartSessionGuid] != null)
			{
				Cart cartFromSession = (Cart) HttpContext.Session[CartTask.CartSessionGuid];
				cart = _cartTask.GetCartByGuid(cartFromSession.CartGuid);
			}

    		return View(cart);
        }

        /// <summary>
        /// Logika dodawania do koszyka z kontrolera (zrobiłem tak bo są 2 metody normalna i axajowa)
        /// </summary>
        /// <param name="id"></param>
        private void AddToBasketLogic(int id)
        {
        	Cart cart = GetCart();

            // Jesli uzytkownik jest zalogowany od razu ustawiamy go na koszyku.
            if (RightPrincipal.CurrentUser != null)
            {
                cart.User = _userRepository.Get(RightPrincipal.CurrentUser.Id);
            }

            // Dodajemy tylko jesli nie istniał już produkt.
            Cart updatedCart = _cartTask.AddProductToCart(cart, id);
            HttpContext.Session[CartTask.CartSessionGuid] = updatedCart;
        }
		/// <summary>
		/// Dodanie produktu do koszyka.
		/// </summary>
		/// <returns></returns>
        [HttpGet]
		[Transaction]
		public ActionResult AddProduct(int id)
		{
            AddToBasketLogic(id);
			TempData[ActionConfirmation.TempDataKey] = ActionConfirmation.CreateSuccess("Dodano produkt do koszyka");
			return this.RedirectToAction(c => c.Index());
		}

        /// <summary>
        /// Dodanie produktu do koszyka ajaxowe
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        [Transaction]
        public ActionResult AddProductAjax(int id)
        {
            AddToBasketLogic(id);
            //Musimy jeszcze odświerzyć koszyk pod menu
            if (HttpContext.Session[CartTask.CartSessionGuid] != null)
            {
                Cart cart = (Cart)HttpContext.Session[CartTask.CartSessionGuid];
                var cartJson = new { amount = cart.Amount, sum = cart.SumPriceBrutto };
                return Json(cartJson, JsonRequestBehavior.AllowGet);
            }
            return Json(null, JsonRequestBehavior.AllowGet);
        } 


		[HttpPost]
		[Transaction]
		[ValidateAntiForgeryToken]
        public ActionResult CashBox(Cart cart)
        {
			if(cart != null && !string.IsNullOrWhiteSpace(cart.CartGuid))
			{
				Cart cartFromDb =
					_cartRepository.GetQuery().FirstOrDefault(c => c.CartGuid == cart.CartGuid && c.User.Id == RightPrincipal.CurrentUser.Id);

				if (cartFromDb != null)
				{
					if (cartFromDb.CartItems.Count == 0)
					{
						return this.RedirectToAction(c => c.CashBox());
					}

					User user = _userRepository.Get(RightPrincipal.CurrentUser.Id);
					_cartTask.CreateOrder(cartFromDb, user);
					
					// Musimy od razu stworzyc nowy koszyk, tak aby do starego koszyka juz nie dodac przypadkiem.
					HttpContext.Session[CartTask.CartSessionGuid] = _cartTask.CreateCart(user);
				}
			}

			TempData[ActionConfirmation.TempDataKey] = ActionConfirmation.CreateSuccess("Zamówienie zostało stworzone. Produkt niedługo pojawi się na twojej półce.");
			return this.RedirectToAction<HomeController>(c => c.Index());
        }
        
		[HttpGet]
        [Transaction]
		public ActionResult DeleteProduct(int id)
		{
			Cart cart = GetCart();

			// Dodajemy tylko jesli nie istniał już produkt.
			Cart updatedCart = _cartTask.RemoveProductFromCart(cart, id);
			HttpContext.Session[CartTask.CartSessionGuid] = updatedCart;

			TempData[ActionConfirmation.TempDataKey] = ActionConfirmation.CreateSuccess("Usunięto produkt z koszyka");
			return this.RedirectToAction(c => c.Index());
        }
        /// <summary>
        /// Usunięcie produktu z koszyka ajaxowe
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpPost]
        [Transaction]
        public ActionResult DeleteProductAjax(int id)
        {
            Cart cart = GetCart();
            // Dodajemy tylko jesli nie istniał już produkt.
            Cart updatedCart = _cartTask.RemoveProductFromCart(cart, id);
            HttpContext.Session[CartTask.CartSessionGuid] = updatedCart;
            var cartJson = new { amount = updatedCart.Amount, sum = updatedCart.SumPriceBrutto };
            return Json(cartJson, JsonRequestBehavior.AllowGet);
        }

		/// <summary>
		/// Opróżnianie koszyka.
		/// </summary>
		/// <returns></returns>
		[HttpGet]
		[Transaction]
		public ActionResult EmptyCart()
		{
			Cart cart = GetCart();
			cart = _cartTask.EmptyCart(cart);
			HttpContext.Session[CartTask.CartSessionGuid] = cart;

			return this.RedirectToAction(c => c.Index());
		}

		/// <summary>
		/// Kasa.
		/// </summary>
		/// <returns></returns>
		[HttpGet]
		public ActionResult CashBox()
		{
			if (RightPrincipal.CurrentUser == null)
			{
				return this.RedirectToAction<HomeController>(c => c.LogOnPage(@"/Cart/CashBox"));
			}

			if(HttpContext.Session[CartTask.CartSessionGuid] == null)
			{
				return this.RedirectToAction(c => c.Index());
			}

			CartViewModel cartViewModel = new CartViewModel();
			Cart cartInSession = (Cart) HttpContext.Session[CartTask.CartSessionGuid];

			// Upewniany sie, ze do koszyka przypisany jest uzytkownik systemu.
			Cart cart = _cartTask.GetCartByGuid(cartInSession.CartGuid);

			if (cart.CartItems.Count == 0)
			{
				return this.RedirectToAction(c => c.CashBox());
			}

			cart.User = _userRepository.Get(RightPrincipal.CurrentUser.Id);
			cart = _cartRepository.SaveOrUpdate(cart);

			cartViewModel.Cart = cart;

			return View(cartViewModel);
		}
    }
}
